package com.redhat.auth.application.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.redhat.auth.security.util.ResourceCacheUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.dayatang.domain.InstanceFactory;
import com.dayatang.querychannel.service.QueryChannelService;
import com.redhat.auth.application.RoleApplication;
import com.redhat.auth.core.AuthResourceBundleI18nService;
import com.redhat.auth.domain.FunctionEntity;
import com.redhat.auth.domain.Role;
import com.redhat.auth.domain.Role.Status;

/**
 * 系统角色管理application实现 <br />
 * 
 * @author vakin.Jiang 2010-4-30
 */
@Service(value = "roleAppliaction")
public class RoleApplicationImpl implements RoleApplication {

	// 查询通道
	protected static QueryChannelService queryChannel;

	protected static QueryChannelService queryChannel() {
		if (queryChannel == null) {
			queryChannel = InstanceFactory
					.getInstance(QueryChannelService.class);
		}
		return queryChannel;
	}

	public Role createRole(Role role) {
		return role.create();
	}

	public void deleteRoleById(Long id) {

		Role r = getRoleById(id);
		if (r == null) {
			throw new RuntimeException(AuthResourceBundleI18nService
					.getMessage("auth.role.roleIsNotExist", "当前角色不存在"));
		}
		r.delete();

	}

	public Long getCount(Role search) {

		StringBuffer hql = new StringBuffer("from Role r where 1=1");
		Object[] obj = createQueryParams(search, hql);

		return queryChannel().queryResultSize(hql.toString(), obj);
	}

	public Role getRoleById(Long id) {
		Role role = Role.getRoleRepository().get(id);
		if (role == null)
			throw new RuntimeException(AuthResourceBundleI18nService
					.getMessage("auth.role.roleIsNotExist", "当前角色不存在"));
		return role;
	}

	public Role updateRole(Role role) {
		return role.update();

	}

	public List<Role> queryAllByPage(Role search, int currentPage, int pageSize) {

		StringBuffer hql = new StringBuffer("from Role r where 1=1");
		Object[] obj = createQueryParams(search, hql);
		List<Role> list = queryChannel().queryResult(hql.toString(), obj);

		return list;

	}

	public Role addPermissions(Long id, String[] funIds) {

		Role currentRole = getRoleById(id);

		// 当前角色拥有的权限
		Set<FunctionEntity> ownPermissions = currentRole.getFunctionEntities();
		// 新权限集合
		Set<FunctionEntity> newPermissions = new HashSet<FunctionEntity>();

		for (String funId : funIds) {
			if (false == haveThisPermission(newPermissions, ownPermissions,
					funId)) {
				FunctionEntity entity = FunctionEntity.get(
								Long.parseLong(funId));
				newPermissions.add(entity);
			}
		}

		currentRole.authorize(newPermissions);
		ResourceCacheUtil.removeAllResourceCache();
		return currentRole;
	}

	public void changeStatus(Long id, Status status) {
		Role currentRole = getRoleById(id);
		if (Status.ENABLED.equals(status))
			currentRole.enabled();
		else
			currentRole.disabled();

	}

	/**
	 * 根据功能实体集合判断是否包含某实体ID 如果包含则新增至新的权限集合中
	 * 
	 * @param ownPermissions
	 * @param funId
	 * @return
	 */
	private boolean haveThisPermission(Set<FunctionEntity> newPermissions,
			Set<FunctionEntity> ownPermissions, String funId) {
		boolean have = false;
		for (FunctionEntity functionEntity : ownPermissions) {
			if (funId.equals(functionEntity.getId() + "")) {
				newPermissions.add(functionEntity);
				have = true;
				break;
			}
		}
		return have;
	}

	/**
	 * 构造查询条件
	 * 
	 * @param search
	 * @param hql
	 * @return
	 */
	private Object[] createQueryParams(Role search, StringBuffer hql) {
		List<Object> params = new ArrayList<Object>();
		if (search != null) {
			if (StringUtils.isNotBlank(search.getName())) {
				hql.append(" and r.name like ?");
				params.add("%" + search.getName() + "%");
			}

			if (search.getStatus() != null) {
				hql.append(" and r.status=?");
				params.add(search.getStatus());
			}
		}
		Object[] obj = params.isEmpty() ? new Object[] {} : params.toArray();
		return obj;
	}

}
